﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerCommon.Utility
{
    public interface IObjectItem
    {
        bool ObjectValid { get; set; }

        void Visual_Constructor();
        void Visual_Destructor();
    }

    public interface IObjectPool
    {
        object Alloc();
        void Free(object obj);
        int GetFreeCount();
        int GetAllocSum();
    }

    public class ObjectPool<T> : IObjectPool where T : class, IObjectItem, new()
    {
        private Queue<T> _free;

        private int _incCapt;

        // 当前创建的对象个数
        private int _allocSum;

        public ObjectPool(int initCapt, int incCapt)
        {
            _free = new Queue<T>();
            _incCapt = incCapt;
            _allocSum = 0;
            Create(initCapt);
        }

        public T Alloc()
        {
            if (_free.Count <= 0)
            {
                Create(_incCapt);
            }

            T obj = _free.Dequeue();
            obj.ObjectValid = true;
            obj.Visual_Constructor();
            return obj;
        }

        public T PreAlloc()
        {
            Create(1);
            return _free.Dequeue();
        }

        public void Free(T obj)
        {
            if (obj == null)
            {
                return;
            }

            obj.Visual_Destructor();
            obj.ObjectValid = false;
            _free.Enqueue(obj);
        }

        object IObjectPool.Alloc()
        {
            return Alloc();
        }

        public void Free(object obj)
        {
            this.Free(obj as T);
        }

        private void Create(int capacity)
        {
            for (int i = 0; i < capacity; i++)
            {
                _free.Enqueue(new T());
            }
            _allocSum += capacity;
        }

        private void Destory(int count)
        {
            if (count == -1)
            {
                _free.Clear();
            }
            else
            {
                for (int i = 0; i < count; i++)
                {
                    _free.Dequeue();
                }
            }
        }

        public int GetFreeCount()
        {
            return _free.Count;
        }

        public int GetAllocSum()
        {
            return _allocSum;
        }
    }
}
